package com.java.base.exercise.selftomcat;

import lombok.SneakyThrows;
import sun.misc.PerfCounter;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.Method;

/**
 * @Author RenPu
 * @Date 2023/2/9 14:38
 * @Version 1.0
 * @Description: 根据tomcat的运行原理，模拟实现
 **/
public class MyClassLoaderTest {

    static class MyClassLoader extends ClassLoader{

        //class文件存储的文件夹路径
        private String classPath;

        public MyClassLoader(String classPath){
            this.classPath=classPath;
        }

        private byte[] loadByte(String name) throws Exception {

            //路径特殊符号转换
            name  = name.replaceAll("\\.", "/");

            //文件读取流根据文件夹，文件名称拼接的路径进行读取
            FileInputStream file = new FileInputStream(classPath + "/" + name + ".class");
            int len = file.available();  //获取内容长度
            byte[] data=new byte[len];   //初始化存放字节内容的容器
            file.read(data);             //文件流将内容写入到字节数组
            file.close();                //释放资源
            return data;
        }



        protected Class<?> findClass(String name) {

            try {
                byte[] bytes = loadByte(name);
                return defineClass(name,bytes,0,bytes.length);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }


        @Override
        protected Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
            synchronized(this.getClassLoadingLock(var1)) {
                Class var4 = this.findLoadedClass(var1);
                if (var4 == null) {
                    long var5 = System.nanoTime();
                    if (var4 == null) {
                        long var7 = System.nanoTime();
                        //打破双亲委派的核心代码
                        if(!var1.startsWith("com.ft.test")){
                            var4=this.getParent().loadClass(var1);
                        }else {
                            var4 = findClass(var1);
                        }

                        PerfCounter.getParentDelegationTime().addTime(var7 - var5);
                        PerfCounter.getFindClassTime().addElapsedTimeFrom(var7);
                        PerfCounter.getFindClasses().increment();
                    }
                }

                if (var2) {
                    this.resolveClass(var4);
                }
                return var4;
            }
        }



    }


    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader("D:/FT");
        Class<?> clzz = classLoader.loadClass("com.ft.test.Student");
        Object o = clzz.newInstance();
        Method method = clzz.getDeclaredMethod("sout", null);
        method.invoke(o,null);
        System.out.println(clzz.getClassLoader());


        MyClassLoader classLoader1 = new MyClassLoader("D:/FT1");
        Class<?> clzz1 = classLoader1.loadClass("com.ft.test.Student");
        Object o1 = clzz1.newInstance();
        Method method1 = clzz1.getDeclaredMethod("sout", null);
        method1.invoke(o1,null);
        System.out.println(clzz1.getClassLoader());


    }


}
